package com.example.book.common.executor.implement;

import com.example.book.common.executor.interfaces.ExecutorAsyncService;
import com.example.book.common.utils.Constants;
import com.example.book.crawler.entity.CrawlerContent;
import com.example.book.crawler.pageprocessor.ContentPageProcessor;
import com.example.book.in.entity.BookCatalog;
import com.example.book.in.entity.BookContent;
import com.example.book.in.service.BookCatalogService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import us.codecraft.webmagic.ResultItems;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.downloader.HttpClientDownloader;
import us.codecraft.webmagic.pipeline.Pipeline;
import us.codecraft.webmagic.proxy.Proxy;
import us.codecraft.webmagic.proxy.SimpleProxyProvider;

import java.util.Date;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

/**
 * @author haocj
 * 异步线程任务实现类
 */
@Service
public class ExecutorAsyncServiceImpl implements ExecutorAsyncService {

    private static final Logger logger = LoggerFactory.getLogger(ExecutorAsyncServiceImpl.class);

    @Autowired
    private BookCatalogService bookCatalogService;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    @Async("asyncServiceExecutor")
    public void executeAsync() {
        logger.info("start executeAsync");
        Random r = new Random();
        int i = r.nextInt(10000) + 2000;
        System.out.println("异步线程开始要做的事情");
        try {
            Thread.sleep(i);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("执行了" + i + "的时间");

        logger.info("end executeAsync");
    }

    @Override
    public void saveCatalogByStatus(CrawlerContent crawlerContent, BookCatalog bookCatalog, Map<String, Object> map) {
        try {
            Spider spider = null;
            if (map != null) {
                // 开启IP代理 如果没有取到IP则使用本地IP
                HttpClientDownloader downloader = new HttpClientDownloader();
                downloader.setProxyProvider(SimpleProxyProvider.from(
                        new Proxy(map.get("ip").toString(), Integer.parseInt(map.get("port").toString()))
                ));
                spider = new Spider(new ContentPageProcessor()).setDownloader(downloader);
            } else {
                spider = new Spider(new ContentPageProcessor());
            }

            // 抓取目录对应的内容
            BookContent bookContent = new BookContent();
            bookContent.setId(UUID.randomUUID().toString().replaceAll("-", ""));
            bookContent.setBookCatalogId(bookCatalog.getId());
            bookContent.setCreateDate(new Date());
            bookContent.setUpdateDate(new Date());
            bookContent.setDelFlag("1");

            spider.setUUID(UUID.randomUUID().toString());
            spider.addUrl(new String[]{crawlerContent.getContentHref()});
            spider.addPipeline(new Pipeline() {
                @Override
                public void process(ResultItems resultItems, Task task) {
                    String content = resultItems.get("content");
                    if (content != null) {
                        bookContent.setContent(content
                                .replace("&amp;a;nbsp&amp;a;nbsp&amp;a;nbsp&amp;a;nbsp","")
                                .replace("手机看书，尽在·无名小说手机版M.wmtxt.coM","")
                        );
                        bookContent.setDelFlag("0");
                    }
                }
            });
            spider.thread(1).run();
            spider.clearPipeline().close();

            if (!bookContent.getDelFlag().equals("1")) {
                bookCatalogService.saveCatalogByStatus(crawlerContent, bookCatalog, bookContent);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (map != null) {
                redisTemplate.opsForList().leftPush(Constants.IP_QUEUE, map);
            }
        }
    }
}
